package com.yunfinal.api.service.db.dao;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.yunfinal.api.service.ApiException;
import com.yunfinal.api.service.ApiService;

import java.util.Arrays;
import java.util.List;

/**
 * Record 通用的一些查询.
 * 后期可以根据情况，进行缓存封装，加快查询速度
 * @author 杜福忠
 */
public abstract class BaseDao extends ApiService {
    public String tableName;
    //如果id不是这个，可以在子类重新赋值
    public String idKey = "id";

    protected String defaultValue = "";
    protected String nameKeyStr;
    protected String[] nameKey;

    /**
     * 在此扩展属性时，继承类会自动爆红，方便进行修改代码
     * @param tableName
     * @param nameKeyStr 方便根据ID获取另外一个字段的业务，常见如根据ID换取name
     */
    public BaseDao(String tableName, String nameKeyStr) {
        this.tableName = tableName;
        this.nameKeyStr = nameKeyStr;
        this.nameKey = nameKeyStr.split(",");
    }

    public String getNameById (Object id) {
        if (isBlank(id)){
            return defaultValue;
        }
        Record record = findById(id);
        if (isBlank(record)){
            return defaultValue;
        }
        StringBuilder ret = new StringBuilder();
        String val;
        for (String name : nameKey) {
            val = record.getStr(name);
            ret.append(null == val ? defaultValue : val).append(" ");
        }
        return ret.toString();
    }

    public Record findById(Object id) {
        if (isBlank(id)){
            return null;
        }
        return Db.findById(tableName, id);
    }

    /**
     * 根据ID 判断 数据库 是否存在
     *
     * @param id
     * @return isNull true
     */
    public boolean isNullById(Object id) {
        return isNullBy(idKey.concat("="), id);
    }

    /**
     * 根据column 判断 数据库 是否存在
     *
     * @param condStr 数据库字段名的表达式， 可以逗号分隔多个字段的表达式
     * @param val    值必须和 上面 字段的表达式名个数相同，不然会抛 400 错误
     * @return
     */
    public boolean isNullBy(String condStr, Object... val) {
        if (StrKit.isBlank(condStr)) {
            return true;
        }
        CondKv cond = CondKv.by();
        String[] split = condStr.split(",");
        if (split.length != val.length) {
            throw new ApiException("400", "参数值个数，不合法", split.length);
        }
        for (int i = 0; i < split.length; i++) {
            cond.set(split[i], val[i]);
        }
        List<Record> list = find(FindKv.byCond(cond).setLimit(1));
        return list.size() == 0;
    }

    public List<Record> find(FindKv kv) {
        if( ! kv.containsKey("select")){
            kv.setSelect(idKey.concat(", ").concat(nameKeyStr));
        }
        if (!kv.containsKey("table")) {
            kv.setTable(this.tableName);
        }
        List<Record> ret = Db.find(Db.getSqlPara("find", kv));
        return ret;
    }

    public Integer saveOrUpdate(Record r){
        if (null == r) {
            return null;
        }
        if (null == r.get(idKey)) {
            Db.save(tableName, idKey, r);
        }else{
            Db.update(tableName, idKey, r);
        }
        return r.getInt(idKey);
    }

    @Override
    public String toString() {
        return "BaseDao{" +
                "tableName='" + tableName + '\'' +
                ", idKey='" + idKey + '\'' +
                ", defaultValue='" + defaultValue + '\'' +
                ", nameKeyStr='" + nameKeyStr + '\'' +
                ", nameKey=" + Arrays.toString(nameKey) +
                '}';
    }
}
